package com.example.camera;

/*
 * (#)Preview.java 1.0 2013-7-6 2013-7-6 GMT+08:00
 */

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Size;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;

/**
 * @author guoshijie
 * @version $1.0, 2013-7-6 2013-7-6 GMT+08:00
 * @since jdk1.7.0_17
 */
class Preview extends ViewGroup implements SurfaceHolder.Callback {

    private final String Tag = "Preview";
    private SurfaceView mSurfaceView;
    private SurfaceHolder mHolder;
    private Size mPreviewSize;
    private List<Size> mSupportedPreviewSizes;
    private Camera mCamera;
    private MediaRecorder recorder = null;
    public static boolean recording = false; // 是否在录制状态
    private String filename, video_path;
    private boolean turn_on;// 闪光灯
    private int rorate;// 保存是选择角度

    public static final String SCARD_PATH = Environment
	    .getExternalStorageDirectory().getPath();
    public static final String CACHE_VIDEO_PATH = SCARD_PATH
	    + "/.quickreel/cache/myvideo/";// 自己的视频路径

    /**
     * @param context
     * @param attrs
     */
    public Preview(Context context, AttributeSet attrs) {
	super(context, attrs);
	mSurfaceView = new SurfaceView(context);
	addView(mSurfaceView);
	mHolder = mSurfaceView.getHolder();
	mHolder.addCallback(this);
	mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    int numberOfCameras = -1;
    int mCurrentCamera; // Camera ID currently chosen
    int cameraCurrentlyLocked; // Camera ID that's actually acquired
    int mDefaultCameraId;

    public void setCamera(Camera camera) {
	mCamera = camera;
	if (mCamera != null) {
	    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
		numberOfCameras = Camera.getNumberOfCameras();
		// Find the ID of the rear-facing ("default") camera
		CameraInfo cameraInfo = new CameraInfo();
		for (int i = 0; i < numberOfCameras; i++) {
		    Camera.getCameraInfo(i, cameraInfo);
		    if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
			mCurrentCamera = mDefaultCameraId = i;
			LogUtil.d(Tag, "检查有几个摄像头" + numberOfCameras);
		    }
		}
	    }

	    mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
	    mCamera.setDisplayOrientation(90);
	    requestLayout();
	}
    }

    public void switchCamera() {
	if (numberOfCameras == 1 || numberOfCameras == -1) {
	    return;
	}

	if (mCamera != null) {
	    mCamera.stopPreview();
	    mCamera.release();
	    mCamera = null;
	}

	mCamera = Camera.open((cameraCurrentlyLocked + 1) % numberOfCameras);
	cameraCurrentlyLocked = (cameraCurrentlyLocked + 1) % numberOfCameras;
	setCamera(mCamera);
	try {
	    mCamera.setPreviewDisplay(mHolder);
	} catch (IOException exception) {
	    Log.e(Tag, "IOException caused by setPreviewDisplay()", exception);
	}
	Camera.Parameters parameters = mCamera.getParameters();
	parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
	requestLayout();

	mCamera.setParameters(parameters);
	mCamera.startPreview();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
	final int width = resolveSize(getSuggestedMinimumWidth(),widthMeasureSpec);
	final int height = resolveSize(getSuggestedMinimumHeight(),heightMeasureSpec);
	setMeasuredDimension(width, height);

	if (mSupportedPreviewSizes != null) {
	    mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width,height);
	}

	if (mCamera != null) {
	    Camera.Parameters parameters = mCamera.getParameters();
	    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
	    mCamera.setParameters(parameters);
	}
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
	if (getChildCount() > 0) {
	    final View child = getChildAt(0);//得到相机布局
	    final int width = r - l;
	    final int height = b - t;
	    int previewWidth = width;
	    int previewHeight = height;	  
	    if (mPreviewSize != null) {
		previewWidth = mPreviewSize.width;
		previewHeight = mPreviewSize.height;
	    }
	    // Center the child SurfaceView within the parent.
	    if (width * previewHeight > height * previewWidth) {
		LogUtil.d(Tag, "横屏");
		final int scaledChildWidth = previewWidth * height/ previewHeight;
		child.layout((width - scaledChildWidth) / 2, 0,(width + scaledChildWidth) / 2, height);
	    } else {
		LogUtil.d(Tag, "竖屏");
		if (previewHeight < previewWidth) {
		    LogUtil.d(Tag, "previewHeight < previewWidth");
		    final int scaledChildHeight = previewWidth * width/ previewHeight;
		    child.layout(0, (height - scaledChildHeight) / 2, width, (height + scaledChildHeight) / 2);
		}
		if (previewWidth < previewHeight) {
		    LogUtil.d(Tag, "previewWidth > previewHeight");
		    final int scaledChildWidth = previewHeight * height / previewWidth;		  
		    child.layout((width - scaledChildWidth) / 2, 0,(width + scaledChildWidth) / 2, height);
		}
	    }
	}
    }

    public void surfaceCreated(SurfaceHolder holder) {
	try {
	    if (mCamera != null) {
		mCamera.setPreviewDisplay(holder);
	    }
	} catch (IOException exception) {
	    mCamera.release();
	    mCamera = null;
	    Log.e(Tag, "IOException caused by setPreviewDisplay()", exception);
	}
	requestLayout();
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
	// Now that the size is known, set up the camera parameters and begin
	// the preview.
	Camera.Parameters parameters = mCamera.getParameters();
	parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
	requestLayout();

	mCamera.setParameters(parameters);
	mCamera.startPreview();
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
	// Surface will be destroyed when we return, so stop the preview.
	if (mCamera != null) {
	    mCamera.stopPreview();
	}
    }

    /**
     * 更加官方demo，得到最佳的预览比例
     * @param sizes
     * @param w
     * @param h
     * @return
     */
    private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
	final double ASPECT_TOLERANCE = 0.1;
	double targetRatio = (double) w / h;
	if (sizes == null)
	    return null;

	Size optimalSize = null;
	double minDiff = Double.MAX_VALUE;

	int targetHeight = h;

	// Try to find an size match aspect ratio and size
	for (Size size : sizes) {
	    double ratio = (double) size.width / size.height;
	    if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
		continue;
	    if (Math.abs(size.height - targetHeight) < minDiff) {
		optimalSize = size;
		minDiff = Math.abs(size.height - targetHeight);
	    }
	}

	// Cannot find the one match the aspect ratio, ignore the requirement
	if (optimalSize == null) {
	    minDiff = Double.MAX_VALUE;
	    for (Size size : sizes) {
		if (Math.abs(size.height - targetHeight) < minDiff) {
		    optimalSize = size;
		    minDiff = Math.abs(size.height - targetHeight);
		}
	    }
	}
	return optimalSize;
    }

    // 录制开始控制
    public void mStartRecord() {
	try {
	    mCamera.stopPreview();
	    mCamera.release();
	    mCamera = null;

	    if (recorder == null)
		recorder = new MediaRecorder();
	    else
		recorder.reset();

	    mCamera = Camera.open(cameraCurrentlyLocked);

	    if (turn_on) {
		Camera.Parameters parameters = mCamera.getParameters();
		parameters.setFlashMode(parameters.FLASH_MODE_TORCH);
		mCamera.setParameters(parameters);
	    }

	    mCamera.setDisplayOrientation(90);
	    mCamera.unlock();

	    recorder.setCamera(mCamera);

	    recording = true;
	    recorder.setPreviewDisplay(mHolder.getSurface());
	    recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
	    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
	    LogUtil.d(Tag, "厂商" + Build.MANUFACTURER);
	    if (Build.MANUFACTURER.toString().equals("samsung")) {
		LogUtil.d(Tag, "--------三星---------");
		recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
		recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
		recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
		recorder.setVideoSize(320, 240);
		recorder.setVideoFrameRate(20);
		recorder.setVideoEncodingBitRate(768000);
	    } else {
		LogUtil.d(Tag, "不是三星");
		CamcorderProfile mProfile = CamcorderProfile.get(0,CamcorderProfile.QUALITY_HIGH);// 240X320
		mProfile.fileFormat = MediaRecorder.OutputFormat.MPEG_4;
		mProfile.videoCodec = MediaRecorder.VideoEncoder.H264;
		mProfile.audioCodec = MediaRecorder.AudioEncoder.AAC;
		mProfile.videoBitRate = 768000 * 2;
		mProfile.videoFrameRate = 20;
		recorder.setProfile(mProfile);
	    }

	    // recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
	    // recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
	    // recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
	    // recorder.setVideoSize(320, 240);
	    // recorder.setVideoFrameRate(20);
	    // recorder.setVideoEncodingBitRate(768000);
	    recorder.setMaxDuration(30 * 1000);//
	    recorder.setMaxFileSize(10 * 1024 * 1024);
	    recorder.setOrientationHint(rorate);
	    // 输出文件的路径和名称
	    File file = new File(CACHE_VIDEO_PATH);
	    if (!file.exists()) {
		file.mkdirs();
	    }
	    SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");// 获取当前时间，进一步转化为字符串
	    Date date = new Date();

	    video_path = file.getAbsolutePath() + File.separator + format.format(date) + ".mp4";
	    filename = format.format(date) + ".mp4";
	    recorder.setOutputFile(video_path);

	    try {
		recorder.prepare();
		recorder.start();
	    } catch (Exception e) {
		e.printStackTrace();
	    }
	    Log.d(Tag, "mStartRecord");
	} catch (IllegalStateException e) {
	    e.printStackTrace();
	} catch (Exception e) {
	    e.printStackTrace();
	}
    }

    private boolean is_comment;

    public void setIs_comment(boolean is_comment) {
	this.is_comment = is_comment;
    }

    // 录制停止控制
    public void mStopRecord() {
	// 判断是否是录制状态
	if (recording) {
	    // 以下停止录制状态，设置状态为false和状态标志为绿色
	    recording = false;
	    // 设置recorder为空的状态，为下次录制做准备
	    recorder.reset();
	    Log.d(Tag, "mStopRecord true");
	}
	Log.d(Tag, "mStopRecord");
    }

    public void Cancle() {
	if (recording) {

	    recording = false;
	    recorder.reset();
	    mCamera.stopPreview();
	    mCamera.release();
	    mCamera = null;
	}
    }

    public boolean isTurn_on() {
	return turn_on;
    }

    public void setTurn_on(boolean turn_on) {
	this.turn_on = turn_on;
    }

    public int getRorate() {
	return rorate;
    }

    public void setRorate(int rorate) {
	this.rorate = rorate;
    }

}
